﻿package com.singlenotion.display.scrollers
{
	import flash.display.MovieClip;
	import flash.events.Event;
	import flash.events.MouseEvent;
	
	import com.singlenotion.events.CustomEvent.v01.CustomEvent;
	
	public class VerticalScroller extends MovieClip
	{
		public static const SLIDER_MOVE:String = "moved";
		public static const SLIDER_PRESS:String = "pressed";
		public static const SLIDER_RELEASE:String = "released";
		public static const VALUE_CHANGE:String = "valueChanged";
		
		private var _bg:MovieClip;
		private var _thumb:MovieClip;
		
		private var _locked:Boolean;
		private var _min:Number;
		private var _max:Number;
		private var _value:Number;
		
		private var _sliderWidth:Number;
		private var _sliderHeight:Number;
		private var _relativeY:Number;
		
		private static var THUMB_NAME:String = "thumb";
		private static var BG_NAME:String = "bg";
		
		public function VerticalScroller($thumb:Class, $bg:Class, $min:Number = 0, $max:Number = 100, $value:Number = 50, $locked:Boolean = false) 
		{	
			_min = $min;
			_max = $max;
			_value = $value;
			
			locked = $locked;
			
			updateBG($bg);
			updateThumb($thumb);
			
			_sliderWidth = bg.width;
			_sliderHeight = bg.height-thumb.height;
			
			setValue($value);
			
			addListeners();
			
			init();
		}
		
		private function init():void
		{
			if (locked) {
				lock();
			} else {
				unlock();
			}
		}
		
		private function updateThumb ($thumb:Class):void
		{
			if (_thumb != null) removeThumb();
			_thumb = new $thumb();
			_thumb.x = bg.x;
			addChild(thumb);
			thumb.name = VerticalScroller.THUMB_NAME;
		}
	  
		private function removeThumb ():void
		{
			removeChild(thumb);
			_thumb = null;
		}
		
		private function updateBG ($bg:Class):void
		{
			if (_bg != null) removeBG();
			_bg = new $bg();
			addChild(bg);
			bg.name = VerticalScroller.BG_NAME;
		}
	  
		private function removeBG ():void
		{
			removeChild(bg);
			_bg = null;
		}
		
		private function setValue ($val:Number):void
		{
			var tmpValue:Number = ($val >= _min && $val <= _max) ? $val : _value;
			if (tmpValue != _value) {
				_value = tmpValue;
				thumb.y = (_sliderHeight * (_value / _max));
				dispatchEvent(new CustomEvent(VerticalScroller.VALUE_CHANGE,false, false, { }));
			}
		}
		
		private function addListeners ():void
		{
			thumb.addEventListener(MouseEvent.MOUSE_DOWN, onThumbDown);
			bg.addEventListener(MouseEvent.CLICK, onTrackClicked);
		}
	  
		private function removeListeners ():void
		{
			thumb.removeEventListener(MouseEvent.MOUSE_DOWN, onThumbDown);
			bg.removeEventListener(MouseEvent.CLICK, onTrackClicked);
		}
		
		private function onTrackClicked($e:MouseEvent):void
		{
		}
		
		private function onThumbDown($e:MouseEvent):void 
		{
			stage.addEventListener( MouseEvent.MOUSE_MOVE, onThumbMove );
			stage.addEventListener( MouseEvent.MOUSE_UP, onThumbUp );
			_relativeY = thumb.mouseY * thumb.scaleY;
			dispatchEvent(new CustomEvent(VerticalScroller.SLIDER_PRESS, false, false, { } ));
		} 
		
		private function onThumbUp($e:MouseEvent):void 
		{
			stage.removeEventListener( MouseEvent.MOUSE_MOVE, onThumbMove );
			stage.removeEventListener( MouseEvent.MOUSE_UP, onThumbUp );
			dispatchEvent(new CustomEvent(VerticalScroller.SLIDER_RELEASE, false, false, { } ));
		}
		
		private function onThumbMove($e:MouseEvent):void 
		{
			setValue(_max*(Math.max(bg.y, Math.min(bg.y + bg.mouseY - _relativeY, bg.y + bg.height - thumb.height))/_sliderHeight));
			$e.updateAfterEvent();
			dispatchEvent(new CustomEvent(VerticalScroller.SLIDER_MOVE,false, false, { }));
		}
		
		public function lock():void
		{
			thumb.buttonMode = false;
			removeListeners();
			locked = true;
			this.alpha = 0.3;
			dispatchEvent(new CustomEvent("locked",false, false, { }));
		}
		
		public function unlock():void
		{
			thumb.buttonMode = true;
			addListeners();
			locked = false;
			this.alpha = 1;
			dispatchEvent(new CustomEvent("unlocked",false, false, { }));
		}
		
		public function get bg():MovieClip { return _bg; }
		
		public function get thumb():MovieClip { return _thumb; }
		
		public function get locked():Boolean { return _locked; }
		
		public function set locked($value:Boolean):void 
		{
			_locked = $value;
		}
		
		public function get min():Number { return _min; }
		
		public function get max():Number { return _max; }
		
		public function get value():Number 
		{ 
			return _value; 
		}
		
		public function set value($value:Number):void
		{
			setValue($value);
		}
	}
}